R Markdown
(Copied from this)
You can use R Markdown (.Rmd) to:
- save and execute code
- generate high quality, reproducible reports that can be shared with
an audience
Basic structure consists of:
- YAML metadata
- Text (markdown)
- Code chunks
Can edit in Visual mode, more like a Word doc. (Click on ‘Visual’,
next to ‘Source’ at the top of the code editor.)
To see your R markdown output file (e.g. html), you knit the .Rmd
file by clicking the Knit button at the top of the code editor or
ctrl-shift-k.
YAML
The YAML header is used to set the output format and output
options.
Here, we’ve added a table of contents using the toc: true.
Have a look at the cheat sheet and
try to add some more features:
Exercise: Make the table of contents floating.
Add toc_float: TRUE to the YAML.
Exercise: Give an option to download the .Rmd source code.
Add code_download: TRUE to the YAML.
Exercise: Hide all the code chunks by default and allow users to
show/hide code as desired.
Add code_folding: “hide” to the YAML.
We can generate a custom R markdown template to use in the
future.
Text
Makes clear documentation easier.
You can navigate through the headers (#Heading 1, ##Heading 2 etc)
like a table of contents in the code editor by clicking ‘Outline’ in the
top right.
Have a look at the cheat sheet and
try the following exercises.
Exercise: Bold and italicise some words in the list below.
- Always leave a blank line between a list and the text above for the
bullet points to render properly
- assessing current practice (italics)
- recording an action plan (bold)
- monitoring quality improvement
Exercise: Create a link to the page on Impact reports on the NICE
website.
See impact
reports.
Exercise: Embed an image of the NICE logo
and add some alt text.
This standard method doesn’t seem to allow adding alt text, but the
text in the square brackets is displayed as a caption at the bottom of
the image.
Need to use this method with fig.alt in chunk options for alt
text.
knitr::include_graphics("https://www.nice.org.uk/Media/Default/About/Branding-guidelines/Logos/master-logo1.png")

This line contains some inline code to
give the time of rendering: 2022-06-08 13:05:26.
Code chunks
Exercise: Insert a code chunk. Try using a keyboard shortcut
(ctrl-alt-i).
Labelling your chunks (e.g. ‘load_doacs’ in the chunk below) means
you can navigate to each section easily via the button at the bottom of
the code editor (orange square with hash symbol).
Tabs
A demo using the DOACS data from before.
The line chart and table sections are in tabs below the header ‘Tabs’
because we’ve specified {.tabset}.
You should run all the chunks above a chunk before running the chunk
itself to make sure your code works sequentially, when working in the
code editor (i.e. not knitting). Click on the grey triangle with the
green bar (‘Run all chunks above’) in the top right of a chunk
(ctrl-alt-shift-p).
To run a chunk, ctrl-shift-enter with the cursor anywhere in the
chunk (or the green play button).
Line chart
Exercise: Plot a line chart showing prescribing of all doacs over the
last 2 years (reuse previous code from DOACS exercises). Try making it
interactive by using the function ggplotly() from the plotly package
(install the package first).
Table
There are many
packages available for plotting tables in R markdown.
We’ll use reactable
here. Install the package.
Exercise: Modify this table to make it filterable and searchable. Try
using
an aggregate function to give the sum items for each chemical.
doacs_df %>%
filter(year(date) == 2020) %>%
group_by(chemical, date) %>%
summarise(sum_items = sum(items)) %>%
reactable(
.,
filterable = TRUE,
searchable = TRUE,
groupBy = "chemical",
columns = list(
sum_items = colDef(aggregate = "sum")
)
)
Chunk options
Chunk options allow control over chunk outputs. See some options
here.
Exercise: Add an option to the load_doacs chunk so the chunk still
runs, but is not shown in the final document.
Add include = FALSE to the chunk. Remember to use a comma after the
chunk label when adding chunk options.
Exercise: Add an option to the doacs_line chunk to hide the code
which generates the line graph.
Add echo = FALSE to the chunk. echo prevents the code from appearing
in the output file but not the results of the code. It’s often used for
figures, where you want to show a chart but hide the code which
generated the chart.
Exercise: Add an option to the doacs_table chunk to hide the message
about summarise grouping.
Add message = FALSE.
Exercise: Override the global options in the setup chunk so every
chunk runs and any results are generated, but the code is not shown.
Change to echo = FALSE in knitr::opts_chunk$set(echo = TRUE). We want
to use echo = FALSE rather than include = FALSE as we still want to see
our line chart and table.
Parameters
You can include
parameters to rerun a report with different values. Parameters are
specified in the YAML, given a default value (here, year: 2020), and
used via params$name (e.g. params$year). (Note the backslash in here
between params and name, visible only the .Rmd, is to escape the
markdown syntax as dollar signs are used to display equations in
markdown.)
# Changing the year to a parameter
doacs_df %>%
filter(year(date) == params$year) %>%
group_by(chemical, date) %>%
summarise(sum_items = sum(items)) %>%
reactable(
.,
groupBy = "chemical"
)
Exercise: Try re-rendering the report with the year 2021 using the
Rstudio IDE.
Click on the triangle next to ‘Knit’, ‘Knit with Parameters’, change
2020 to 2021.
LS0tDQp0aXRsZTogIlIgbWFya2Rvd24gYmFzaWNzIg0KYXV0aG9yOiAiSW1wYWN0IHRlYW0iDQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiDQpvdXRwdXQ6IA0KICAgIGh0bWxfZG9jdW1lbnQ6DQogICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICAgICAgY29kZV9kb3dubG9hZDogVFJVRQ0KICAgICAgICBjb2RlX2ZvbGRpbmc6ICJoaWRlIg0KcGFyYW1zOg0KICAgIHllYXI6IDIwMjANCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkocGxvdGx5KQ0KbGlicmFyeShyZWFjdGFibGUpDQpgYGANCg0KIyBSIE1hcmtkb3duDQoNCihDb3BpZWQgZnJvbSBbdGhpc10oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vbGVzc29uLTEuaHRtbCkpDQoNCllvdSBjYW4gdXNlIFIgTWFya2Rvd24gKC5SbWQpIHRvOg0KDQotIHNhdmUgYW5kIGV4ZWN1dGUgY29kZQ0KLSBnZW5lcmF0ZSBoaWdoIHF1YWxpdHksIHJlcHJvZHVjaWJsZSByZXBvcnRzIHRoYXQgY2FuIGJlIHNoYXJlZCB3aXRoIGFuIGF1ZGllbmNlDQoNCkJhc2ljIHN0cnVjdHVyZSBjb25zaXN0cyBvZjoNCg0KLSBZQU1MIG1ldGFkYXRhDQotIFRleHQgKG1hcmtkb3duKQ0KLSBDb2RlIGNodW5rcw0KDQpDYW4gZWRpdCBpbiBWaXN1YWwgbW9kZSwgbW9yZSBsaWtlIGEgV29yZCBkb2MuIChDbGljayBvbiAnVmlzdWFsJywgbmV4dCB0byAnU291cmNlJyBhdCB0aGUgdG9wIG9mIHRoZSBjb2RlIGVkaXRvci4pDQoNClRvIHNlZSB5b3VyIFIgbWFya2Rvd24gb3V0cHV0IGZpbGUgKGUuZy4gaHRtbCksIHlvdSBrbml0IHRoZSAuUm1kIGZpbGUgYnkgY2xpY2tpbmcgdGhlIEtuaXQgYnV0dG9uIGF0IHRoZSB0b3Agb2YgdGhlIGNvZGUgZWRpdG9yIG9yIGN0cmwtc2hpZnQtay4NCg0KIyBZQU1MDQoNClRoZSBZQU1MIGhlYWRlciBpcyB1c2VkIHRvIHNldCB0aGUgb3V0cHV0IGZvcm1hdCBhbmQgb3V0cHV0IG9wdGlvbnMuDQoNCkhlcmUsIHdlJ3ZlIGFkZGVkIGEgdGFibGUgb2YgY29udGVudHMgdXNpbmcgdGhlIHRvYzogdHJ1ZS4NCg0KSGF2ZSBhIGxvb2sgYXQgdGhlIFtjaGVhdCBzaGVldF0oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vbGVzc29uLTE1Lmh0bWwpIGFuZCB0cnkgdG8gYWRkIHNvbWUgbW9yZSBmZWF0dXJlczoNCg0KPiBFeGVyY2lzZTogTWFrZSB0aGUgdGFibGUgb2YgY29udGVudHMgZmxvYXRpbmcuDQoNCkFkZCB0b2NfZmxvYXQ6IFRSVUUgdG8gdGhlIFlBTUwuDQoNCj4gRXhlcmNpc2U6IEdpdmUgYW4gb3B0aW9uIHRvIGRvd25sb2FkIHRoZSAuUm1kIHNvdXJjZSBjb2RlLg0KDQpBZGQgY29kZV9kb3dubG9hZDogVFJVRSB0byB0aGUgWUFNTC4NCg0KPiBFeGVyY2lzZTogSGlkZSBhbGwgdGhlIGNvZGUgY2h1bmtzIGJ5IGRlZmF1bHQgYW5kIGFsbG93IHVzZXJzIHRvIHNob3cvaGlkZSBjb2RlIGFzIGRlc2lyZWQuDQoNCkFkZCBjb2RlX2ZvbGRpbmc6ICJoaWRlIiB0byB0aGUgWUFNTC4NCg0KV2UgY2FuIGdlbmVyYXRlIGEgY3VzdG9tIFIgbWFya2Rvd24gdGVtcGxhdGUgdG8gdXNlIGluIHRoZSBmdXR1cmUuDQoNCiMgVGV4dA0KDQpNYWtlcyBjbGVhciBkb2N1bWVudGF0aW9uIGVhc2llci4NCg0KWW91IGNhbiBuYXZpZ2F0ZSB0aHJvdWdoIHRoZSBoZWFkZXJzICgjSGVhZGluZyAxLCAjI0hlYWRpbmcgMiBldGMpIGxpa2UgYSB0YWJsZSBvZiBjb250ZW50cyBpbiB0aGUgY29kZSBlZGl0b3IgYnkgY2xpY2tpbmcgJ091dGxpbmUnIGluIHRoZSB0b3AgcmlnaHQuDQoNCkhhdmUgYSBsb29rIGF0IHRoZSBbY2hlYXQgc2hlZXRdKGh0dHBzOi8vcm1hcmtkb3duLnJzdHVkaW8uY29tL2xlc3Nvbi0xNS5odG1sKSBhbmQgdHJ5IHRoZSBmb2xsb3dpbmcgZXhlcmNpc2VzLg0KDQo+IEV4ZXJjaXNlOiBCb2xkIGFuZCBpdGFsaWNpc2Ugc29tZSB3b3JkcyBpbiB0aGUgbGlzdCBiZWxvdy4NCg0KLSBBbHdheXMgbGVhdmUgYSBibGFuayBsaW5lIGJldHdlZW4gYSBsaXN0IGFuZCB0aGUgdGV4dCBhYm92ZSBmb3IgdGhlIGJ1bGxldCBwb2ludHMgdG8gcmVuZGVyIHByb3Blcmx5DQotIGFzc2Vzc2luZyAqY3VycmVudCBwcmFjdGljZSogKGl0YWxpY3MpDQotIHJlY29yZGluZyAqKmFuIGFjdGlvbiBwbGFuKiogKGJvbGQpDQotIG1vbml0b3JpbmcgcXVhbGl0eSBpbXByb3ZlbWVudA0KDQo+IEV4ZXJjaXNlOiBDcmVhdGUgYSBsaW5rIHRvIHRoZSBwYWdlIG9uIEltcGFjdCByZXBvcnRzIG9uIHRoZSBOSUNFIHdlYnNpdGUuDQoNClNlZSBbaW1wYWN0IHJlcG9ydHNdKGh0dHBzOi8vd3d3Lm5pY2Uub3JnLnVrL2Fib3V0L3doYXQtd2UtZG8vaW50by1wcmFjdGljZS9tZWFzdXJpbmctdGhlLXVwdGFrZS1vZi1uaWNlLWd1aWRhbmNlL2ltcGFjdC1vZi1ndWlkYW5jZSkuDQoNCj4gRXhlcmNpc2U6IEVtYmVkIGFuIFtpbWFnZSBvZiB0aGUgTklDRSBsb2dvXShodHRwczovL3d3dy5uaWNlLm9yZy51ay9icmFuZC9vdXItbG9nbykgYW5kIGFkZCBzb21lIGFsdCB0ZXh0Lg0KDQpUaGlzIHN0YW5kYXJkIG1ldGhvZCBkb2Vzbid0IHNlZW0gdG8gYWxsb3cgYWRkaW5nIGFsdCB0ZXh0LCBidXQgdGhlIHRleHQgaW4gdGhlIHNxdWFyZSBicmFja2V0cyBpcyBkaXNwbGF5ZWQgYXMgYSBjYXB0aW9uIGF0IHRoZSBib3R0b20gb2YgdGhlIGltYWdlLg0KDQohW05JQ0UgbG9nb10oaHR0cHM6Ly93d3cubmljZS5vcmcudWsvTWVkaWEvRGVmYXVsdC9BYm91dC9CcmFuZGluZy1ndWlkZWxpbmVzL0xvZ29zL21hc3Rlci1sb2dvMS5wbmcpDQoNCk5lZWQgdG8gdXNlIHRoaXMgbWV0aG9kIHdpdGggZmlnLmFsdCBpbiBjaHVuayBvcHRpb25zIGZvciBhbHQgdGV4dC4NCg0KYGBge3IsIGZpZy5hbHQgPSAiTklDRSBsb2dvIn0NCmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5uaWNlLm9yZy51ay9NZWRpYS9EZWZhdWx0L0Fib3V0L0JyYW5kaW5nLWd1aWRlbGluZXMvTG9nb3MvbWFzdGVyLWxvZ28xLnBuZyIpDQpgYGANCg0KDQo8IS0tIFdoYXQgZG8geW91IHRoaW5rIHRoaXMgbGluZSBpcz8gSXQncyBhIGNvbW1lbnQgKGN0cmwtc2hpZnQtYykgLS0+DQoNClRoaXMgbGluZSBjb250YWlucyBzb21lIFtpbmxpbmUgY29kZV0oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vbGVzc29uLTQuaHRtbCkgdG8gZ2l2ZSB0aGUgdGltZSBvZiByZW5kZXJpbmc6IGByIG5vdygpYC4NCg0KIyBDb2RlIGNodW5rcw0KDQo+IEV4ZXJjaXNlOiBJbnNlcnQgYSBjb2RlIGNodW5rLiBUcnkgdXNpbmcgYSBrZXlib2FyZCBzaG9ydGN1dCAoY3RybC1hbHQtaSkuDQoNCkxhYmVsbGluZyB5b3VyIGNodW5rcyAoZS5nLiAnbG9hZF9kb2FjcycgaW4gdGhlIGNodW5rIGJlbG93KSBtZWFucyB5b3UgY2FuIG5hdmlnYXRlIHRvIGVhY2ggc2VjdGlvbiBlYXNpbHkgdmlhIHRoZSBidXR0b24gYXQgdGhlIGJvdHRvbSBvZiB0aGUgY29kZSBlZGl0b3IgKG9yYW5nZSBzcXVhcmUgd2l0aCBoYXNoIHN5bWJvbCkuDQoNCiMjIFRhYnMgey50YWJzZXR9DQoNCkEgZGVtbyB1c2luZyB0aGUgRE9BQ1MgZGF0YSBmcm9tIGJlZm9yZS4NCg0KVGhlIGxpbmUgY2hhcnQgYW5kIHRhYmxlIHNlY3Rpb25zIGFyZSBpbiB0YWJzIGJlbG93IHRoZSBoZWFkZXIgJ1RhYnMnIGJlY2F1c2Ugd2UndmUgc3BlY2lmaWVkIHsudGFic2V0fS4NCg0KWW91IHNob3VsZCBydW4gYWxsIHRoZSBjaHVua3MgYWJvdmUgYSBjaHVuayBiZWZvcmUgcnVubmluZyB0aGUgY2h1bmsgaXRzZWxmIHRvIG1ha2Ugc3VyZSB5b3VyIGNvZGUgd29ya3Mgc2VxdWVudGlhbGx5LCB3aGVuIHdvcmtpbmcgaW4gdGhlIGNvZGUgZWRpdG9yIChpLmUuIG5vdCBrbml0dGluZykuIENsaWNrIG9uIHRoZSBncmV5IHRyaWFuZ2xlIHdpdGggdGhlIGdyZWVuIGJhciAoJ1J1biBhbGwgY2h1bmtzIGFib3ZlJykgaW4gdGhlIHRvcCByaWdodCBvZiBhIGNodW5rIChjdHJsLWFsdC1zaGlmdC1wKS4NCg0KVG8gcnVuIGEgY2h1bmssIGN0cmwtc2hpZnQtZW50ZXIgd2l0aCB0aGUgY3Vyc29yIGFueXdoZXJlIGluIHRoZSBjaHVuayAob3IgdGhlIGdyZWVuIHBsYXkgYnV0dG9uKS4NCg0KYGBge3IgbG9hZF9kb2FjcywgaW5jbHVkZSA9IEZBTFNFfQ0KIyBNYWtlIHN1cmUgdGhpcyAuUm1kIGlzIHNhdmVkIGluIHRoZSBzYW1lIGZvbGRlciBhcyB3aGVyZSB0aGUgRE9BQ1MgZGF0YXNldCBmcm9tIHRoZSBwcmV2aW91cyBzZXNzaW9uIGlzDQojIENoYW5nZSB0aGUgZmlsZSBuYW1lIHRvIHdoYXRldmVyIHlvdSd2ZSBzYXZlZCBpdCBhcw0KZG9hY3NfZGYgPC0gcmVhZF9jc3YoIkRPQUNTX2RhdGEuY3N2IiwgDQogICAgICAgICAgICAgICAgICAgICBjb2xfdHlwZXMgPSAiRGNjY2RkZCIpDQpgYGANCg0KIyMjIExpbmUgY2hhcnQNCg0KPiBFeGVyY2lzZTogUGxvdCBhIGxpbmUgY2hhcnQgc2hvd2luZyBwcmVzY3JpYmluZyBvZiBhbGwgZG9hY3Mgb3ZlciB0aGUgbGFzdCAyIHllYXJzIChyZXVzZSBwcmV2aW91cyBjb2RlIGZyb20gRE9BQ1MgZXhlcmNpc2VzKS4gVHJ5IG1ha2luZyBpdCBpbnRlcmFjdGl2ZSBieSB1c2luZyB0aGUgZnVuY3Rpb24gZ2dwbG90bHkoKSBmcm9tIHRoZSBwbG90bHkgcGFja2FnZSAoaW5zdGFsbCB0aGUgcGFja2FnZSBmaXJzdCkuDQoNCmBgYHtyIGRvYWNzX2xpbmUsIG1lc3NhZ2UgPSBGQUxTRSwgZWNobyA9IEZBTFNFfQ0KDQpnIDwtIGRvYWNzX2RmICU+JSANCiAgICBmaWx0ZXIoeWVhcihkYXRlKSAlaW4lIGMoMjAyMCwgMjAyMSkpICU+JSANCiAgICBncm91cF9ieShjaGVtaWNhbCwgZGF0ZSkgJT4lIA0KICAgIHN1bW1hcmlzZSh0b3RhbCA9IHN1bShpdGVtcykpICU+JSANCiAgICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdG90YWwsIGNvbG91ciA9IGNoZW1pY2FsKSkgKw0KICAgIGdlb21fbGluZSgpDQoNCmdncGxvdGx5KGcpDQoNCmBgYA0KDQojIyMgVGFibGUNCg0KVGhlcmUgYXJlIFttYW55IHBhY2thZ2VzIGF2YWlsYWJsZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLWNvb2tib29rL3RhYmxlLW90aGVyLmh0bWwpIGZvciBwbG90dGluZyB0YWJsZXMgaW4gUiBtYXJrZG93bi4NCg0KV2UnbGwgdXNlIFtyZWFjdGFibGVdKGh0dHBzOi8vZ2xpbi5naXRodWIuaW8vcmVhY3RhYmxlLykgaGVyZS4gSW5zdGFsbCB0aGUgcGFja2FnZS4NCg0KPiBFeGVyY2lzZTogTW9kaWZ5IHRoaXMgdGFibGUgdG8gbWFrZSBpdCBmaWx0ZXJhYmxlIGFuZCBzZWFyY2hhYmxlLiBUcnkgW3VzaW5nIGFuIGFnZ3JlZ2F0ZSBmdW5jdGlvbl0oaHR0cHM6Ly9nbGluLmdpdGh1Yi5pby9yZWFjdGFibGUvYXJ0aWNsZXMvZXhhbXBsZXMuaHRtbCNncm91cGluZy1hbmQtYWdncmVnYXRpb24pIHRvIGdpdmUgdGhlIHN1bSBpdGVtcyBmb3IgZWFjaCBjaGVtaWNhbC4NCg0KYGBge3IgZG9hY3NfdGFibGUsIG1lc3NhZ2UgPSBGQUxTRX0NCmRvYWNzX2RmICU+JSANCiAgICBmaWx0ZXIoeWVhcihkYXRlKSA9PSAyMDIwKSAlPiUgDQogICAgZ3JvdXBfYnkoY2hlbWljYWwsIGRhdGUpICU+JSANCiAgICBzdW1tYXJpc2Uoc3VtX2l0ZW1zID0gc3VtKGl0ZW1zKSkgJT4lIA0KICAgIHJlYWN0YWJsZSgNCiAgICAgICAgLiwNCiAgICAgICAgZmlsdGVyYWJsZSA9IFRSVUUsDQogICAgICAgIHNlYXJjaGFibGUgPSBUUlVFLA0KICAgICAgICBncm91cEJ5ID0gImNoZW1pY2FsIiwNCiAgICAgICAgY29sdW1ucyA9IGxpc3QoDQogICAgICAgICAgICBzdW1faXRlbXMgPSBjb2xEZWYoYWdncmVnYXRlID0gInN1bSIpDQogICAgICAgICkNCiAgICApDQpgYGANCg0KIyMgQ2h1bmsgb3B0aW9ucw0KDQpDaHVuayBvcHRpb25zIGFsbG93IGNvbnRyb2wgb3ZlciBjaHVuayBvdXRwdXRzLiBTZWUgW3NvbWUgb3B0aW9ucyBoZXJlXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tMy5odG1sKS4NCg0KPiBFeGVyY2lzZTogQWRkIGFuIG9wdGlvbiB0byB0aGUgbG9hZF9kb2FjcyBjaHVuayBzbyB0aGUgY2h1bmsgc3RpbGwgcnVucywgYnV0IGlzIG5vdCBzaG93biBpbiB0aGUgZmluYWwgZG9jdW1lbnQuDQoNCkFkZCBpbmNsdWRlID0gRkFMU0UgdG8gdGhlIGNodW5rLiBSZW1lbWJlciB0byB1c2UgYSBjb21tYSBhZnRlciB0aGUgY2h1bmsgbGFiZWwgd2hlbiBhZGRpbmcgY2h1bmsgb3B0aW9ucy4NCg0KPiBFeGVyY2lzZTogQWRkIGFuIG9wdGlvbiB0byB0aGUgZG9hY3NfbGluZSBjaHVuayB0byBoaWRlIHRoZSBjb2RlIHdoaWNoIGdlbmVyYXRlcyB0aGUgbGluZSBncmFwaC4NCg0KQWRkIGVjaG8gPSBGQUxTRSB0byB0aGUgY2h1bmsuIGVjaG8gcHJldmVudHMgdGhlIGNvZGUgZnJvbSBhcHBlYXJpbmcgaW4gdGhlIG91dHB1dCBmaWxlIGJ1dCBub3QgdGhlIHJlc3VsdHMgb2YgdGhlIGNvZGUuIEl0J3Mgb2Z0ZW4gdXNlZCBmb3IgZmlndXJlcywgd2hlcmUgeW91IHdhbnQgdG8gc2hvdyBhIGNoYXJ0IGJ1dCBoaWRlIHRoZSBjb2RlIHdoaWNoIGdlbmVyYXRlZCB0aGUgY2hhcnQuDQoNCj4gRXhlcmNpc2U6IEFkZCBhbiBvcHRpb24gdG8gdGhlIGRvYWNzX3RhYmxlIGNodW5rIHRvIGhpZGUgdGhlIG1lc3NhZ2UgYWJvdXQgc3VtbWFyaXNlIGdyb3VwaW5nLg0KDQpBZGQgbWVzc2FnZSA9IEZBTFNFLg0KDQo+IEV4ZXJjaXNlOiBPdmVycmlkZSB0aGUgZ2xvYmFsIG9wdGlvbnMgaW4gdGhlIHNldHVwIGNodW5rIHNvIGV2ZXJ5IGNodW5rIHJ1bnMgYW5kIGFueSByZXN1bHRzIGFyZSBnZW5lcmF0ZWQsIGJ1dCB0aGUgY29kZSBpcyBub3Qgc2hvd24uDQoNCkNoYW5nZSB0byBlY2hvID0gRkFMU0UgaW4ga25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKS4gV2Ugd2FudCB0byB1c2UgZWNobyA9IEZBTFNFIHJhdGhlciB0aGFuIGluY2x1ZGUgPSBGQUxTRSBhcyB3ZSBzdGlsbCB3YW50IHRvIHNlZSBvdXIgbGluZSBjaGFydCBhbmQgdGFibGUuDQoNCiMjIFBhcmFtZXRlcnMNCg0KWW91IGNhbiBbaW5jbHVkZSBwYXJhbWV0ZXJzXShodHRwczovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbS9sZXNzb24tNi5odG1sKSB0byByZXJ1biBhIHJlcG9ydCB3aXRoIGRpZmZlcmVudCB2YWx1ZXMuIFBhcmFtZXRlcnMgYXJlIHNwZWNpZmllZCBpbiB0aGUgWUFNTCwgZ2l2ZW4gYSBkZWZhdWx0IHZhbHVlIChoZXJlLCB5ZWFyOiAyMDIwKSwgYW5kIHVzZWQgdmlhIHBhcmFtc1wkbmFtZSAoZS5nLiBwYXJhbXMkeWVhcikuIChOb3RlIHRoZSBiYWNrc2xhc2ggaW4gaGVyZSBiZXR3ZWVuIHBhcmFtcyBhbmQgbmFtZSwgdmlzaWJsZSBvbmx5IHRoZSAuUm1kLCBpcyB0byBlc2NhcGUgdGhlIG1hcmtkb3duIHN5bnRheCBhcyBkb2xsYXIgc2lnbnMgYXJlIHVzZWQgdG8gZGlzcGxheSBlcXVhdGlvbnMgaW4gbWFya2Rvd24uKQ0KDQpgYGB7ciBkb2Fjc190YWJsZV9wYXJhbXMsIG1lc3NhZ2UgPSBGQUxTRX0NCiMgQ2hhbmdpbmcgdGhlIHllYXIgdG8gYSBwYXJhbWV0ZXINCmRvYWNzX2RmICU+JSANCiAgICBmaWx0ZXIoeWVhcihkYXRlKSA9PSBwYXJhbXMkeWVhcikgJT4lIA0KICAgIGdyb3VwX2J5KGNoZW1pY2FsLCBkYXRlKSAlPiUgDQogICAgc3VtbWFyaXNlKHN1bV9pdGVtcyA9IHN1bShpdGVtcykpICU+JSANCiAgICByZWFjdGFibGUoDQogICAgICAgIC4sDQogICAgICAgIGdyb3VwQnkgPSAiY2hlbWljYWwiDQogICAgKQ0KYGBgDQoNCj4gRXhlcmNpc2U6IFRyeSByZS1yZW5kZXJpbmcgdGhlIHJlcG9ydCB3aXRoIHRoZSB5ZWFyIDIwMjEgdXNpbmcgdGhlIFJzdHVkaW8gSURFLg0KDQpDbGljayBvbiB0aGUgdHJpYW5nbGUgbmV4dCB0byAnS25pdCcsICdLbml0IHdpdGggUGFyYW1ldGVycycsIGNoYW5nZSAyMDIwIHRvIDIwMjEuDQoNCiMgUmVzb3VyY2VzDQoNCi0gW1I0RFMgY2hhcHRlciBvbiBSIG1hcmtkb3duXShodHRwczovL3I0ZHMuaGFkLmNvLm56L3ItbWFya2Rvd24uaHRtbCNyLW1hcmtkb3duKQ0KLSBbTkhTLVIgY29tbXVuaXR5IFIgbWFya2Rvd24gd29ya3Nob3BdKGh0dHBzOi8veW91dHUuYmUvUmFNNmZnd01aSXMpDQotIFtDaGVhdCBzaGVldF0oaHR0cHM6Ly93d3cucnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLykNCi0gW1IgbWFya2Rvd24gY29va2Jvb2tdKGh0dHBzOi8vYm9va2Rvd24ub3JnL3lpaHVpL3JtYXJrZG93bi1jb29rYm9vay8pDQotIFtSIG1hcmtkb3duOiBUaGUgRGVmaW5pdGl2ZSBHdWlkZV0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvcm1hcmtkb3duLykNCg==